package com.quanyan.ic.vendingMachine.http.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by zhuo.shi on 2017/8/1.
 * 打印http请求日志
 */
@Aspect
@Component
public class LogInterceptor implements Ordered {

    private static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Pointcut("execution(* com.quanyan..*Controller.*(..))")
    public void controller() {
    }

    @Around(value = "controller()")
    public Object profile(ProceedingJoinPoint poj) throws Throwable {
        try {
            Object result = poj.proceed(); //处理业务流程
            printLog(poj.getSignature(), poj.getArgs(), result); //打印日志
            return result;
        } catch (Exception e) {
            printLog(poj.getSignature(), poj.getArgs(), e.getMessage()); //打印异常
            throw e;
        }
    }

    private static final String[] HEADERS_TO_TRY = {
            "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED", "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP", "HTTP_FORWARDED_FOR", "HTTP_FORWARDED", "HTTP_VIA", "REMOTE_ADDR"
    };

    public String getClientIpAddress(HttpServletRequest request) {
        for (String header : HEADERS_TO_TRY) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
                return ip;
            }
        }
        return request.getRemoteAddr();
    }

    private void printLog(final Signature signature, Object[] args, final Object result) {
        try {
            Object[] tmpArgs = new Object[args.length];
            int i = 0;
            for (Object o : args) {
                if (o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof MultipartFile) {
                    continue;
                }
                tmpArgs[i++] = o;
            }
            HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            logger.info("[requestIP     ] : {}", getClientIpAddress(httpServletRequest));
            logger.info("[requestURI    ] : {}", httpServletRequest.getRequestURI());
            logger.info("[requestParam  ] : {}", JSON.toJSONString(httpServletRequest.getParameterMap()));
            logger.info("[callMethod    ] : {}", signature.toString());
            logger.info("[args          ] : {}", JSONArray.toJSONString(tmpArgs));
            logger.info("[result        ] : {}", result != null ? result.toString() : "null");

        } catch (Exception e) {
            logger.error("log exception {}", e);
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }
}